package com.basker.pisces.orm.parser;

import java.text.MessageFormat;
import java.util.List;

import org.apache.commons.lang3.NotImplementedException;

import com.basker.pisces.core.datasource.DbInfo;
import com.basker.pisces.orm.data.meta.FieldMeta;
import com.basker.pisces.orm.data.meta.IndexMeta;
import com.basker.pisces.orm.data.meta.TableMeta;
import com.basker.pisces.orm.session.ISqlSession;
import com.basker.pisces.orm.statement.InsertCommand;

public class SqlServerParser extends AbstractSqlParser {

    @Override
    public String getAddFieldSql(TableMeta tableMeta, FieldMeta fieldMeta) {
        throw new NotImplementedException("SqlServerParser.getAddFieldSql is not impl!");
    }

    @Override
    public String getCreateIndexSql(TableMeta tableMeta, IndexMeta indexMeta) {
        throw new NotImplementedException("SqlServerParser.getCreateIndexSql is not impl!");
    }

    @Override
    public String getCreateSchemaSql(DbInfo dbInfo, ISqlSession sqlSession) {
        throw new NotImplementedException("SqlServerParser.getCreateSchemaSql is not impl!");
    }

    @Override
    public String getCreateTableSql(TableMeta tableMeta) {
        throw new NotImplementedException("SqlServerParser.getCreateTableSql is not impl!");
    }

    @Override
    public String getModifyFieldSql(TableMeta tableMeta, FieldMeta fieldMeta) {
        throw new NotImplementedException("SqlServerParser.getModifyFieldSql is not impl!");
    }

    @Override
    public String getSynFieldSql(TableMeta tableMeta, FieldMeta fieldMeta) {
        throw new NotImplementedException("SqlServerParser.getSynFieldSql is not impl!");
    }

    @Override
    public String getSynIndexSql(TableMeta tableMeta, IndexMeta indexMeta) {
        throw new NotImplementedException("SqlServerParser.getSynIndexSql is not impl!");
    }

    @Override
    public List<DBColumnInfo> getTableColumns(TableMeta tableMeta, ISqlSession sqlSession) {
        throw new NotImplementedException("SqlServerParser.getTableColumns is not impl!");
    }

    @Override
    public List<DBIndexInfo> getTableIndexes(TableMeta tableMeta, ISqlSession sqlSession) {
        throw new NotImplementedException("SqlServerParser.getTableIndexes is not impl!");
    }

    @Override
    public String resolvePageSql(String originalSql, int pageIndex, int pageSize) {
        boolean hasOrderByClause = originalSql.indexOf("ORDER BY") > -1
                || originalSql.toUpperCase().indexOf("ORDER BY") > -1;
        if (hasOrderByClause) {
            // 有orderby 可以使用Offset Fetch Next 排序，对sqlserver2012有效
            int offset = pageSize * (pageIndex - 1);
            int next = pageSize;

            return originalSql + " OFFSET " + offset + " ROWS FETCH NEXT " + next + " ROWS ONLY";
        } else {
            int start = pageSize * (pageIndex - 1) + 1;
            int end = start + pageSize - 1;

            String select = this.resolveSelect(originalSql);
            String orderBy = "(SELECT 0)";

            // int orderByIndex = originalSql.toUpperCase().indexOf("ORDER BY");
            // if (orderByIndex > -1) {
            // orderBy = this.resolveOderBy(originalSql);
            // originalSql = this.resolveOriginalSql(originalSql);
            // }

            StringBuilder sql = new StringBuilder();

            sql.append("SELECT ");
            sql.append(select);
            sql.append(" FROM ( SELECT ");
            sql.append(select);
            sql.append(",ROW_NUMBER() OVER (ORDER BY ");
            sql.append(orderBy);
            sql.append(") AS ROWNUMBER FROM(");
            sql.append(originalSql);
            sql.append(") AS TA) AS TA WHERE ROWNUMBER BETWEEN ");
            sql.append(start);
            sql.append(" AND ");
            sql.append(end);
            sql.append(" ORDER BY ROWNUMBER");

            return sql.toString();
        }
    }

    @Override
    protected String genInsertSql(TableMeta tableMeta, InsertCommand insertCommand) {
        String insertSql = super.genInsertSql(tableMeta, insertCommand);
        return MessageFormat.format("SET IDENTITY_INSERT {0} ON;{1};", tableMeta.getName(), insertSql);
    }

    private String resolveSelect(String originalSql) {
        int start = "SELECT".length();
        int end = originalSql.indexOf("FROM");
        if (end < 0) {
            end = originalSql.toUpperCase().indexOf("FROM");
        }

        String select = originalSql.substring(start, end).trim();
        String[] selectFields = select.split(",");
        String[] resolvedSelectFields = new String[selectFields.length];

        for (int i = 0; i < resolvedSelectFields.length; i++) {
            String[] splits = selectFields[i].split(" AS ");
            if (splits.length == 0) {
                splits = selectFields[i].split(" as ");
            }
            String field = splits.length == 0 ? splits[0].trim() : splits[1].trim();

            resolvedSelectFields[i] = field;
        }

        return String.join(",", resolvedSelectFields);
    }

}
